home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -in_the_mag- / workbench / scanning / stscan / vectorop.c < prev    next >
C/C++ Source or Header  |  2000-03-05  |  8KB  |  334 lines

  1. /*
  2. **      $VER: vectorop.c 3.00D (11.8.97)
  3. **
  4. **      STScan vectorization routines
  5. **
  6. **      Written by Frank-Christian Kruegel, Henning Peters, Andreas R. Kleinert
  7. **      GNU General Public License V2
  8. */
  9.  
  10. #include "stscan.h"
  11.  
  12. #define REGION_SIZE 64
  13. #define CHAINLEN 16384
  14.  
  15. static UWORD __far chpixels[2][CHAINLEN];
  16. static UWORD __far lnpixels[2][CHAINLEN];
  17. static UWORD __far regio_x[128][128];
  18. static UWORD __far regio_y[128][128];
  19. static UBYTE __far regio_done[128][128];
  20. static UBYTE __far regio_numx,regio_numy;
  21. static char str_filenam[256]="";
  22. static UWORD maxdiff=4;
  23.  
  24. static UBYTE getpixel(UWORD x,UWORD y)
  25. {
  26.  UBYTE res;
  27.  
  28.  res = (UBYTE) (*(memptr+(ULONG)y*(ULONG)membpl+(ULONG)(x>>3))&bitval[x&7])?0:1;
  29.  
  30.  return(res);
  31. }
  32.  
  33. static void clrpixel(UWORD x,UWORD y)
  34. { *(memptr+(ULONG)y*(ULONG)membpl+(ULONG)(x>>3))|=bitval[x&7];
  35. }
  36.  
  37. static void setpixel(UWORD x,UWORD y)
  38. { *(memptr+(ULONG)y*(ULONG)membpl+(ULONG)(x>>3))&=invbitval[x&7];
  39. }
  40.  
  41. static UBYTE subiter(UWORD nx,UWORD ny)
  42. { UWORD x,y;
  43.   UBYTE f,vw,vnw,vn,vne,ve,vse,vs,vsw;
  44.  
  45.   f=0;
  46.   for (y=regio_y[nx][ny];y<regio_y[nx][ny+1];y++)
  47.   { for (x=regio_x[nx][ny];x<regio_x[nx+1][ny];x++)
  48.     { if ((getpixel(x,y))&&((x&1)==(y&1)))
  49.       { vw= getpixel(x-1,y);
  50.         vnw=getpixel(x-1,y-1);
  51.         vn= getpixel(x  ,y-1);
  52.         vne=getpixel(x+1,y-1);
  53.         ve= getpixel(x+1,y);
  54.         vse=getpixel(x+1,y+1);
  55.         vs= getpixel(x  ,y+1);
  56.         vsw=getpixel(x-1,y+1);
  57.         if ( (( ((vw^1)&(vnw|vn))
  58.                +((vn^1)&(vne|ve))
  59.                +((ve^1)&(vse|vs))
  60.                +((vs^1)&(vsw|vw)) )==1)
  61.             || ((!(vw))&&(!(vnw))&&(!(vn))&&(!(vne))&&
  62.                 (!(ve))&&(!(vse))&&(!(vs))&&(!(vsw)) ) )
  63.         { clrpixel(x,y);
  64.           if (!(f)) f=((vnw|vse)&(vne|vsw)&(vn|vs)&(vw|ve));
  65.         }
  66.       }
  67.     }
  68.   }
  69.   for (y=regio_y[nx][ny];y<regio_y[nx][ny+1];y++)
  70.   { for (x=regio_x[nx][ny];x<regio_x[nx+1][ny];x++)
  71.     { if ((getpixel(x,y))&&((x&1)!=(y&1)))
  72.       { vw= getpixel(x-1,y);
  73.         vnw=getpixel(x-1,y-1);
  74.         vn= getpixel(x  ,y-1);
  75.         vne=getpixel(x+1,y-1);
  76.         ve= getpixel(x+1,y);
  77.         vse=getpixel(x+1,y+1);
  78.         vs= getpixel(x  ,y+1);
  79.         vsw=getpixel(x-1,y+1);
  80.         if ( (( ((vw^1)&(vnw|vn))
  81.                +((vn^1)&(vne|ve))
  82.                +((ve^1)&(vse|vs))
  83.                +((vs^1)&(vsw|vw)) )==1)
  84.             || ((!(vw))&&(!(vnw))&&(!(vn))&&(!(vne))&&
  85.                 (!(ve))&&(!(vse))&&(!(vs))&&(!(vsw)) ) )
  86.         { clrpixel(x,y);
  87.           if (!(f)) f=((vnw|vse)&(vne|vsw)&(vn|vs)&(vw|ve));
  88.         }
  89.       }
  90.     }
  91.   }
  92.   return(f);
  93. }
  94.  
  95. static UBYTE chkblack(UWORD nx,UWORD ny)
  96. { UWORD x,y;
  97.   UBYTE f=1;
  98.   for (y=regio_y[nx][ny];y<regio_y[nx][ny+1];y++)
  99.   { for (x=regio_x[nx][ny];x<regio_x[nx+1][ny];x++)
  100.     if (!(getpixel(x,y)))
  101.     { f=0;
  102.       y=regio_y[nx][ny+1];
  103.       x=regio_x[nx+1][ny];
  104.     }
  105.   }
  106.   return(f);
  107. }
  108.  
  109. static void straighten(void)
  110. { UWORD x,y;
  111.   UBYTE vnw,vne,vse,vsw;
  112.  
  113.   for (y=1;y<memheight-1;y++)
  114.   { for (x=1;x<memwidth-1;x++)
  115.     { if ((getpixel(x,y))
  116.           &&(!(getpixel(x-1,y)))&&(!(getpixel(x+1,y)))
  117.           &&(!(getpixel(x,y-1)))&&(!(getpixel(x,y+1))))
  118.       { vnw=getpixel(x-1,y-1);
  119.         vne=getpixel(x+1,y-1);
  120.         vse=getpixel(x+1,y+1);
  121.         vsw=getpixel(x-1,y+1);
  122.         if (((vnw))&&(!(vne))&&(!(vse))&&((vsw)))
  123.         { clrpixel(x,y);
  124.           setpixel(x-1,y);
  125.         }
  126.         else if ((!(vnw))&&((vne))&&((vse))&&(!(vsw)))
  127.         { clrpixel(x,y);
  128.           setpixel(x+1,y);
  129.         }
  130.         else if (((vnw))&&((vne))&&(!(vse))&&(!(vsw)))
  131.         { clrpixel(x,y);
  132.           setpixel(x,y-1);
  133.         }
  134.         else if ((!(vnw))&&(!(vne))&&((vse))&&((vsw)))
  135.         { clrpixel(x,y);
  136.           setpixel(x,y+1);
  137.         }
  138.       }
  139.     }
  140.   }
  141. }
  142.  
  143. void thin(void)
  144. { UWORD x,y,i;
  145.   ULONG pgofs1,pgofs2;
  146.   char wtitel[96];
  147.   UBYTE p,f,ende;
  148.  
  149.  
  150.   membpl=(memwidth>>3);
  151.   pgofs1=(memwidth>>3)*(memheight-1);
  152.   for (i=0;i<(memwidth>>3);i++)
  153.   { *(memptr+i)=255;
  154.     *(memptr+pgofs1+i)=255;
  155.   }
  156.   pgofs1=0;
  157.   pgofs2=membpl-1;
  158.   for (i=0;i<memheight;i++)
  159.   { *(memptr+pgofs1)|=128;
  160.     *(memptr+pgofs2)|=1;
  161.     pgofs1+=membpl;
  162.     pgofs2+=membpl;
  163.   }
  164.   p=1;
  165.   regio_numx=memwidth/REGION_SIZE;
  166.   regio_numy=memheight/REGION_SIZE;
  167.   regio_x[0][0]=1;
  168.   regio_x[1][0]=REGION_SIZE+(memwidth%REGION_SIZE)/2;
  169.   for (x=2;x<regio_numx;x++) regio_x[x][0]=REGION_SIZE+regio_x[x-1][0];
  170.   regio_x[regio_numx][0]=memwidth-1;
  171.   for (x=0;x<regio_numx;x++) regio_y[x][0]=1;
  172.   for (x=0;x<=regio_numx;x++)
  173.   { regio_y[x][1]=REGION_SIZE+(memheight%REGION_SIZE)/2;
  174.     regio_x[x][1]=regio_x[x][0];
  175.   }
  176.   for (y=2;y<regio_numy;y++) for (x=0;x<=regio_numx;x++)
  177.   { regio_y[x][y]=REGION_SIZE+regio_y[x][y-1];
  178.     regio_x[x][y]=regio_x[x][0];
  179.   }
  180.   for (x=0;x<regio_numx;x++) regio_y[x][regio_numy]=memheight-1;
  181.   for (y=0;y<regio_numy;y++) for (x=0;x<regio_numx;x++) regio_done[x][y]=1;
  182.   do
  183.   { ende=0;
  184.     for (y=0;y<regio_numy;y++) for (x=0;x<regio_numx;x++)
  185.     { if (regio_done[x][y])
  186.       { if (subiter(x,y)) f=regio_done[x][y]=1;
  187.         else if (chkblack(x,y)) f=regio_done[x][y]=1;
  188.         else f=regio_done[x][y]=0;
  189.         ende|=f;
  190.         sprintf(&wtitel[0],"Region (%02d;%02d) Pass %02d",x,y,p);
  191.         SetWindowTitles(win,&wtitel[0],(UBYTE *)-1);
  192.       }
  193.     }
  194.     p++;
  195.   } while (ende);
  196.   SetWindowTitles(win,"Cleanup",(UBYTE *)-1);
  197.   straighten();
  198.   SetWindowTitles(win," ",(UBYTE *)-1);
  199. }
  200.  
  201. static UWORD getchain(UWORD x, UWORD y)
  202. { UWORD lx,ly,pos;
  203.   UBYTE f=1;
  204.  
  205.   lx=x;
  206.   ly=y;
  207.   pos=0;
  208.   while ((f)&&(pos<CHAINLEN))
  209.   { chpixels[0][pos]=lx;
  210.     chpixels[1][pos]=ly;
  211.     clrpixel(lx,ly);
  212.     pos++;
  213.          if (getpixel(lx-1,ly  )) lx--;
  214.     else if (getpixel(lx-1,ly-1)) {lx--; ly--;}
  215.     else if (getpixel(lx  ,ly-1)) ly--;
  216.     else if (getpixel(lx+1,ly-1)) {lx++; ly--;}
  217.     else if (getpixel(lx+1,ly  )) lx++;
  218.     else if (getpixel(lx+1,ly+1)) {lx++; ly++;}
  219.     else if (getpixel(lx  ,ly+1)) ly++;
  220.     else if (getpixel(lx-1,ly+1)) {lx--; ly++;}
  221.     else f=0;
  222.   }
  223.   return(pos);
  224. }
  225.  
  226. static UWORD getline(UWORD x0, UWORD y0, UWORD x1, UWORD y1)
  227. { WORD xdiff,ydiff,xstep,ystep, sum;
  228.   UWORD i;
  229.   WORD step[2]={-1,1};
  230.  
  231.   xstep=step[(x0<x1)]; ystep=step[(y0<y1)];
  232.   xdiff=abs(x0-x1); ydiff=abs(y0-y1);
  233.  
  234.   lnpixels[0][0]=x0;
  235.   lnpixels[1][0]=y0;
  236.   i=1;
  237.   if (xdiff>ydiff)
  238.   { sum=xdiff/2;
  239.     while (x0!=x1)
  240.     { x0+=xstep;
  241.       sum-=ydiff;
  242.       if (sum<0)
  243.       { y0+=ystep;
  244.         sum+=xdiff;
  245.       }
  246.       lnpixels[0][i]=x0;
  247.       lnpixels[1][i]=y0;
  248.       i++;
  249.     }
  250.   }
  251.   else
  252.   { sum=ydiff/2;
  253.     while (y0!=y1)
  254.     { y0+=ystep;
  255.       sum-=xdiff;
  256.       if (sum<0)
  257.       { x0+=xstep;
  258.         sum+=ydiff;
  259.       }
  260.       lnpixels[0][i]=x0;
  261.       lnpixels[1][i]=y0;
  262.       i++;
  263.     }
  264.   }
  265.   return(i);
  266. }
  267.  
  268. static void polygon(UWORD startpos,UWORD len,FILE *vecfile)
  269. { UWORD sx0,sy0,sx1,sy1,m,n,s,lnlen,cbdist,mcbdist,mdpos;
  270.  
  271.   sx0=chpixels[0][startpos];
  272.   sy0=chpixels[1][startpos];
  273.   sx1=chpixels[0][startpos+len-1];
  274.   sy1=chpixels[1][startpos+len-1];
  275.   lnlen=getline(sx0,sy0,sx1,sy1);
  276.   mdpos=0;
  277.   mcbdist=0;
  278.   s=len/lnlen;
  279.   if (s<1) s=1;
  280.   for(m=0,n=startpos;m<lnlen;m++,n+=s)
  281.   { cbdist=abs(chpixels[0][n]-lnpixels[0][m])
  282.           +abs(chpixels[1][n]-lnpixels[1][m]);
  283.     if (cbdist>mcbdist)
  284.     { mdpos=m;
  285.       mcbdist=cbdist;
  286.     }
  287.   }
  288.   if (mcbdist>maxdiff)
  289.   { polygon(startpos,mdpos,vecfile);
  290.     polygon(startpos+mdpos,len-mdpos,vecfile);
  291.   }
  292.   else
  293.   { fprintf(vecfile,"%d %d\n",sx0,memheight-sy0);
  294.     fprintf(vecfile,"%d %d\n\n",sx1,memheight-sy1);
  295.   }
  296. }
  297.  
  298. void vectorize(void)
  299. { UWORD p,x,y,len;
  300.   FILE *vecfile;
  301.   char wtitel[96];
  302.  
  303.   if (filerequest("Speichern Vektor TXT File",str_filenam))
  304.   { p=0;
  305.     membpl=(memwidth>>3);
  306.     vecfile=fopen(str_filenam,"w");
  307.     for (y=1;y<memheight-1;y++)
  308.     { for (x=1;x<memwidth-1;x++)
  309.       { if (getpixel(x,y))
  310.         { len=getchain(x,y);
  311.           polygon(0,len,vecfile);
  312.           sprintf(&wtitel[0],"Chain %04d",++p);
  313.           SetWindowTitles(win,&wtitel[0],(UBYTE *)-1);
  314.         }
  315.       }
  316.     }
  317.     fclose(vecfile);
  318.     SetWindowTitles(win," ",(UBYTE *)-1);
  319.   }
  320. }
  321.  
  322. void chngmaxdiff(void)
  323. {
  324.  ULONG longnum;
  325.  
  326.  longnum = maxdiff;
  327.  
  328.  if(rtGetLong(&longnum, "Enter vectorization accuracy", NULL,
  329.                         RTGL_ShowDefault, TRUE,
  330.                         RTGL_Min,         2,
  331.                         RTGL_Max,         100,
  332.                         TAG_END)) maxdiff=longnum;
  333. }
  334.